package com.finesys.backend.api.interceptors;

import com.finesys.backend.common.model.base.BusinessResult;
import com.finesys.backend.common.model.user.UserModel;
import com.finesys.backend.common.utils.Const;
import com.finesys.backend.common.utils.HttpStatusCodes;
import com.finesys.backend.common.utils.JacksonMapper;
import com.finesys.backend.common.utils.JsonResult;
import com.finesys.backend.service.user.UserService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author lehoon
 * <p>Description: login_interceptor</p>
 * 2020年10月12日
 */
public class LoginHandlerInterceptor extends HandlerInterceptorAdapter{
	public final static JacksonMapper mapper = new JacksonMapper("yyyy-MM-dd HH:mm:ss");
	@DubboReference(version = "1.0.0", timeout = 600000, check = false, mock = "com.finesys.backend.service.user.UserServiceMock")
	private UserService userService;
	
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //HandlerMethod hanlderMethod = (HandlerMethod) handler;
	    String token = request.getHeader(Const.ACCESS_TOKEN_KEY);

	    /**为了兼容swagger测试*/
	    if(StringUtils.isEmpty(token)) {
	        token = request.getParameter(Const.ACCESS_TOKEN_KEY);
        }

        if (StringUtils.isEmpty(token) || token.length() < 64) {
            JsonResult json = new JsonResult();
            json.setCode(HttpStatusCodes.UNAUTHORIZED);
            json.setMessage("当前未登录系统, 请登录");
            writeJson(response, json);
            return false;
        }

        if(userService == null) {
            JsonResult json = new JsonResult();
            json.setCode(HttpStatusCodes.UNAUTHORIZED);
            json.setMessage("当前系统不允许登陆, 请稍后重试");
            writeJson(response, json);
            return false;
        }

        final String remoteAddress = getRemoteAddress(request);
        //check token valid
        if (!userService.checkTokenSign(token, remoteAddress)) {
            JsonResult json = new JsonResult();
            json.setCode(HttpStatusCodes.AUTH_NOTVALID_TOKEN);
            json.setMessage("token签名错误,非法的token,请重新登陆");
            writeJson(response, json);
            return false;
        }

        BusinessResult<UserModel> result = userService.validateToken(token);
        if (!result.isSuccess()) {
            JsonResult json = new JsonResult();
            json.setCode(result.getCode());
            json.setMessage(result.getMessage());
            writeJson(response, json);
            return false;
        }

        if(result.getData() == null) {
            JsonResult json = new JsonResult();
            json.setCode(HttpStatusCodes.UNAUTHORIZED);
            json.setMessage("会话已超时, 请登录");
            writeJson(response, json);
            return false;
        }

        request.setAttribute(Const.CURRENT_USER, result.getData());
        return true;
	}

    private void writeJson(HttpServletResponse response, Object obj) throws IOException {
        response.setContentType("text/json;charset=UTF-8");
        response.getWriter().write(mapper.toJson(obj));
    }

    /**
     * 获取客户端ip地址
     * @return
     */
    public String getRemoteAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
}
